#pragma once

#include "../Shared/GObjHelpers.hpp"

namespace BuildNG
{
  class Module;

  class ErrorLocationInfo
  {
  public:
    Glib::ustring     file_name;
    int               line_number;
    int               column_number;

    void set_not_specified();
  };
  
  class ErrorListener : public Object
  {
  public:
    ErrorListener();
    virtual ~ErrorListener();

    virtual void begin_build_module(Glib::RefPtr<Module> module) { }
    virtual void end_build_module(Glib::RefPtr<Module> module) { }

    virtual void report_error(const ErrorLocationInfo &location_info,const Glib::ustring &msg) { }
    virtual void report_warning(const ErrorLocationInfo &location_info,const Glib::ustring &msg) { }
  };

  class StdErrorListener : public ErrorListener
  {
  public:
    static Glib::RefPtr<StdErrorListener> create();

    virtual void begin_build_module(Glib::RefPtr<Module> module);
    virtual void end_build_module(Glib::RefPtr<Module> module);

    virtual void report_error(const ErrorLocationInfo &location_info,const Glib::ustring &msg);
    virtual void report_warning(const ErrorLocationInfo &location_info,const Glib::ustring &msg);
  };

  // an error listener that creates a "DOM" (ie, an object model of the report "document")
  class DOMErrorListener : public ErrorListener
  {
  public:
    enum Flags
    {
      Flag_IgnoreWarnings = (1 << 0),
    };

    DOMErrorListener(int flags);
    virtual ~DOMErrorListener();

    static Glib::RefPtr<DOMErrorListener> create(int flags);

    virtual void begin_build_module(Glib::RefPtr<Module> module);
    virtual void end_build_module(Glib::RefPtr<Module> module);

    virtual void report_error(const ErrorLocationInfo &location_info,const Glib::ustring &msg);
    virtual void report_warning(const ErrorLocationInfo &location_info,const Glib::ustring &msg);

    enum ErrorType
    {
      ErrorType_Error,
      ErrorType_Warning,
    };

    struct Error
    {
      ErrorType           error_type;
      ErrorLocationInfo   location_info;
      Glib::ustring       msg;
    };
    
    class ModuleReport : public Object
    {
    public:
      Glib::RefPtr<Module>    module;
      std::vector<Error>      errors;
    };
    std::vector<Glib::RefPtr<ModuleReport> >    module_reports;

  private:
    int                           flags;
    Glib::RefPtr<ModuleReport>    cur_module;
  };
}
